#include "gge.h"
#include <SDL_image.h>
//IMG_Linked_Version
static int  LUA_IMG_Init(lua_State *L)
{
    int flags = (int)luaL_optinteger(L, 1,IMG_INIT_JPG|IMG_INIT_PNG|IMG_INIT_TIF|IMG_INIT_WEBP);
    lua_pushboolean(L,IMG_Init(flags)!=0);
    return 1;
}

static int  LUA_IMG_Quit(lua_State *L)
{
    IMG_Quit();
    return 0;
}

static int  LUA_IMG_LoadTyped_RW(lua_State *L)
{
    SDL_RWops * ops = *(SDL_RWops**)luaL_checkudata(L, 1, "SDL_RWops");
    const char *type = luaL_checkstring(L,2);
    SDL_Surface *r = IMG_LoadTyped_RW(ops,0,type);
    if (r){
        SDL_Surface **ud = (SDL_Surface**)lua_newuserdata(L, sizeof (SDL_Surface*));
        *ud = r;
        luaL_setmetatable(L, "SDL_Surface");
        return 1;
    }
    return 0;
}

static int  LUA_IMG_Load(lua_State *L)
{
    const char *path = luaL_checkstring(L, 1);
    Uint32 key = (Uint32)luaL_optinteger(L, 2, 0);

    SDL_Surface *sf = IMG_Load(path);
    if (sf){
        SDL_Surface **ud = (SDL_Surface**)lua_newuserdata(L, sizeof (SDL_Surface*));
        *ud = sf;
        luaL_setmetatable(L, "SDL_Surface");
        return 1;
    }
    return 0;
}

static int  LUA_IMG_LoadARGB8888(lua_State *L)
{
    const char *path = luaL_checkstring(L, 1);
    Uint32 key = (Uint32)luaL_optinteger(L, 2, 0);

    SDL_Surface *sf = IMG_Load(path);
    if (sf){
        if (sf->format->format != SDL_PIXELFORMAT_ARGB8888){
            SDL_Surface *temp = SDL_ConvertSurfaceFormat(sf,SDL_PIXELFORMAT_ARGB8888,SDL_SWSURFACE);
            if(temp){
				if (key != 0)
					SDL_SetColorKey(temp, SDL_TRUE, key);
                SDL_FreeSurface(sf);
                sf = temp;
            }
        }
        SDL_Surface** ud = (SDL_Surface**)lua_newuserdata(L, sizeof (SDL_Surface*));
        *ud = sf;
        luaL_setmetatable(L, "SDL_Surface");
        return 1;
    }
    return 0;
}

static int  LUA_IMG_Load_RW(lua_State *L)
{
    SDL_RWops * rw = *(SDL_RWops**)luaL_checkudata(L, 1, "SDL_RWops");
    Uint32 key = (Uint32)luaL_optinteger(L, 2, 0);

    SDL_Surface *sf = IMG_Load_RW(rw, 0);
    if (sf){
        SDL_Surface **ud = (SDL_Surface**)lua_newuserdata(L, sizeof (SDL_Surface*));
        *ud = sf;
        luaL_setmetatable(L, "SDL_Surface");
        return 1;
    }
    return 0;
}

static int  LUA_IMG_LoadARGB8888_RW(lua_State *L)
{
    SDL_RWops * rw = *(SDL_RWops**)luaL_checkudata(L, 1, "SDL_RWops");
    Uint32 key = (Uint32)luaL_optinteger(L, 2, 0);

    SDL_Surface *sf = IMG_Load_RW(rw, 0);
    if (sf){
        if (sf->format->format != SDL_PIXELFORMAT_ARGB8888){
            SDL_Surface *temp = SDL_ConvertSurfaceFormat(sf,SDL_PIXELFORMAT_ARGB8888,SDL_SWSURFACE);
            if(temp){
				if (key != 0)
					SDL_SetColorKey(temp, SDL_TRUE, key);
                SDL_FreeSurface(sf);
                sf = temp;
            }
        }
        SDL_Surface** ud = (SDL_Surface**)lua_newuserdata(L, sizeof (SDL_Surface*));
        *ud = sf;
        luaL_setmetatable(L, "SDL_Surface");
        return 1;
    }
    return 0;
}

static int  LUA_IMG_LoadTexture(lua_State *L)
{
    SDL_Renderer * rd = *(SDL_Renderer**)luaL_checkudata(L, 1, "SDL_Renderer");
    const char *file = luaL_checkstring(L,2);
    int access = (int)luaL_optinteger(L,3,SDL_TEXTUREACCESS_STATIC);

    if (access == SDL_TEXTUREACCESS_STATIC)
    {
        SDL_Surface* sf = IMG_Load(file);
		if (sf) {
            SDL_Texture* tex = SDL_CreateTextureFromSurface(rd, sf);
			if (tex)
			{
				GGE_Texture* ud = (GGE_Texture*)lua_newuserdata(L, sizeof(GGE_Texture));
				SDL_memset(ud, 0, sizeof(GGE_Texture));
				ud->tex = tex;
                ud->sf = GGE_SurfaceAlphaToSurface(sf, 0);
				luaL_setmetatable(L, "SDL_Texture");
                SDL_FreeSurface(sf);
				return 1;
			}
            SDL_FreeSurface(sf);
		}
    }
    else if (access == SDL_TEXTUREACCESS_STREAMING)
    {
		SDL_Surface* sf = IMG_Load(file);
		if (sf) {
			SDL_Texture* tex = SDL_CreateTexture(rd, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, sf->w, sf->h);

			if (tex) {
				void* pixels = NULL;
				int pitch;
				if (SDL_LockTexture(tex, NULL, &pixels, &pitch) == 0)
				{
                    SDL_ConvertPixels(sf->w, sf->h,sf->format->format,sf->pixels,sf->pitch,
                        SDL_PIXELFORMAT_ARGB8888,pixels,pitch);
					SDL_UnlockTexture(tex);
				}
				GGE_Texture* ud = (GGE_Texture*)lua_newuserdata(L, sizeof(GGE_Texture));
				SDL_memset(ud, 0, sizeof(GGE_Texture));
				ud->tex = tex;
                ud->sf = sf;
				SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
				luaL_setmetatable(L, "SDL_Texture");
				return 1;
			}
		}
    }

    return 0;
}

static int  LUA_IMG_LoadTexture_RW(lua_State *L)
{
    SDL_Renderer * rd = *(SDL_Renderer**)luaL_checkudata(L, 1, "SDL_Renderer");
    SDL_RWops * rw = *(SDL_RWops**)luaL_checkudata(L, 2, "SDL_RWops");
    int access = (int)luaL_optinteger(L,3,SDL_TEXTUREACCESS_STATIC);

	if (access == SDL_TEXTUREACCESS_STATIC)
	{
        SDL_Surface* sf = IMG_Load_RW(rw, 0);
        if (sf)
        {
			SDL_Texture* tex = SDL_CreateTextureFromSurface(rd, sf);
			if (tex)
			{
				GGE_Texture* ud = (GGE_Texture*)lua_newuserdata(L, sizeof(GGE_Texture));
				SDL_memset(ud, 0, sizeof(GGE_Texture));
				ud->tex = tex;
				ud->sf = GGE_SurfaceAlphaToSurface(sf, 0);
				luaL_setmetatable(L, "SDL_Texture");
                SDL_FreeSurface(sf);
				return 1;
			}
            SDL_FreeSurface(sf);
        }
	}
	else if (access == SDL_TEXTUREACCESS_STREAMING)
	{
        SDL_Surface* sf = IMG_Load_RW(rw, 0);
		if (sf) {
			SDL_Texture* tex = SDL_CreateTexture(rd, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, sf->w, sf->h);

			if (tex) {
				void* pixels = NULL;
				int pitch;
				if (SDL_LockTexture(tex, NULL, &pixels, &pitch) == 0)
				{
					SDL_ConvertPixels(sf->w, sf->h, sf->format->format, sf->pixels, sf->pitch,
						SDL_PIXELFORMAT_ARGB8888, pixels, pitch);
					SDL_UnlockTexture(tex);
				}
				GGE_Texture* ud = (GGE_Texture*)lua_newuserdata(L, sizeof(GGE_Texture));
				SDL_memset(ud, 0, sizeof(GGE_Texture));
				ud->tex = tex;
                ud->sf = sf;
				SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
				luaL_setmetatable(L, "SDL_Texture");
				return 1;
			}
		}
	}

    return 0;
}

static int  LUA_IMG_LoadTextureTyped_RW(lua_State *L)
{
    SDL_Renderer * rd = *(SDL_Renderer**)luaL_checkudata(L, 1, "SDL_Renderer");
    SDL_RWops * rw = *(SDL_RWops**)luaL_checkudata(L, 2, "SDL_RWops");
    const char *type = luaL_checkstring(L,3);
    SDL_Texture *tex = IMG_LoadTextureTyped_RW(rd,rw,0,type);
    if (tex){
        GGE_Texture *ud = (GGE_Texture*)lua_newuserdata(L, sizeof (GGE_Texture));
        SDL_memset(ud,0,sizeof (GGE_Texture));
        ud->tex;
        luaL_setmetatable(L, "SDL_Texture");
        return 1;
    }
    return 0;
}

static int  LUA_IMG_SavePNG(lua_State *L)
{
    SDL_Surface * sf = *(SDL_Surface**)luaL_checkudata(L, 1, "SDL_Surface");
    const char *file = luaL_checkstring(L,2);
    lua_pushboolean(L,IMG_SavePNG(sf,file));
    
    return 1;
}
static int  LUA_IMG_SavePNG_RW(lua_State *L)
{
    SDL_Surface * sf = *(SDL_Surface**)luaL_checkudata(L, 1, "SDL_Surface");
    SDL_RWops * ops = *(SDL_RWops**)luaL_checkudata(L, 2, "SDL_RWops");
    int freesrc = (int)luaL_optinteger(L,3,0);
    lua_pushboolean(L,IMG_SavePNG_RW(sf,ops,freesrc));
    return 1;
}

static int  LUA_IMG_SaveJPG(lua_State *L)
{
    SDL_Surface * sf = *(SDL_Surface**)luaL_checkudata(L, 1, "SDL_Surface");
    const char *file = luaL_checkstring(L,2);
    int quality = (int)luaL_optinteger(L,3,90);
    lua_pushboolean(L,IMG_SaveJPG(sf,file,quality));
    return 1;
}

static int  LUA_IMG_SaveJPG_RW(lua_State *L)
{
    SDL_Surface * sf = *(SDL_Surface**)luaL_checkudata(L, 1, "SDL_Surface");
    SDL_RWops * ops = *(SDL_RWops**)luaL_checkudata(L, 2, "SDL_RWops");
    int freesrc = (int)luaL_optinteger(L,3,0);
    int quality = (int)luaL_checkinteger(L,3);
    lua_pushboolean(L,IMG_SaveJPG_RW(sf,ops,freesrc,quality));
    return 1;
}

static const luaL_Reg renderer_funcs[] = {
    {"LoadTexture"         , LUA_IMG_LoadTexture}         ,
    {"LoadTexture_RW"      , LUA_IMG_LoadTexture_RW}      ,
    {"LoadTextureTyped_RW" , LUA_IMG_LoadTextureTyped_RW} ,
    { NULL                 , NULL           }
};

static const luaL_Reg surface_funcs[] = {
    {"SavePNG"    , LUA_IMG_SavePNG}    ,
    {"SavePNG_RW" , LUA_IMG_SavePNG_RW} ,
    {"SaveJPG"    , LUA_IMG_SaveJPG}    ,
    {"SaveJPG_RW" , LUA_IMG_SaveJPG_RW} ,
    { NULL        , NULL            }
};

static const luaL_Reg image_funcs[] = {
    {"Init"         , LUA_IMG_Init}         ,
    {"Quit"         , LUA_IMG_Quit}         ,
    {"Load"         , LUA_IMG_Load}         ,
    {"LoadARGB8888"     , LUA_IMG_LoadARGB8888}         ,
    {"LoadARGB8888_RW"  , LUA_IMG_LoadARGB8888_RW}         ,
    
    
    {"Load_RW"      , LUA_IMG_Load_RW}      ,
    {"LoadTyped_RW" , LUA_IMG_LoadTyped_RW} ,
    { NULL          , NULL          }
};

LUALIB_API int luaopen_gsdl2_image(lua_State *L)
{
    luaL_getmetatable(L,"SDL_Renderer");
    luaL_setfuncs(L,renderer_funcs,0);
    lua_pop(L, 1);
    luaL_getmetatable(L,"SDL_Surface");
    luaL_setfuncs(L,surface_funcs,0);
    lua_pop(L, 1);

    luaL_newlib(L,image_funcs);
    return 1;
}
//IMG_isICO
//IMG_isCUR
//IMG_isBMP
//IMG_isGIF
//IMG_isJPG
//IMG_isLBM
//IMG_isPCX
//IMG_isPNG
//IMG_isPNM
//IMG_isSVG
//IMG_isTIF
//IMG_isXCF
//IMG_isXPM
//IMG_isXV
//IMG_isWEBP

//IMG_LoadICO_RW
//IMG_LoadCUR_RW
//IMG_LoadBMP_RW
//IMG_LoadGIF_RW
//IMG_LoadJPG_RW
//IMG_LoadLBM_RW
//IMG_LoadPCX_RW
//IMG_LoadPNG_RW
//IMG_LoadPNM_RW
//IMG_LoadSVG_RW
//IMG_LoadTGA_RW
//IMG_LoadTIF_RW
//IMG_LoadXCF_RW
//IMG_LoadXPM_RW
//IMG_LoadXV_RW
//IMG_LoadWEBP_RW

//IMG_ReadXPMFromArray